#ifndef _MATRIX_KEYBOARD_H_
#define _MATRIX_KEYBOARD_H_

#include "matrix_keyboard_config.h"
#include "polsys_mcu.h"

#if (_KEYBOARD_VER <= 8)
    #define _KEYBOARD_IDLE_VER_VALUE    0XFF
    typedef u8 key_ver_t;
#elif (_KEYBOARD_VER <= 16)
    #define _KEYBOARD_IDLE_VER_VALUE    0XFFFF
    typedef u16 key_ver_t;
#else
    #error "not suport this large keyboard.\r\n"
#endif

#if (_KEYBOARD_HOR <= 8)
    typedef u8 key_hor_t;
#elif (_KEYBOARD_HOR <= 16)
    typedef u16 key_hor_t;
#else
    #error "not suport this large keyboard.\r\n"
#endif

// 按键坐标值
typedef union _key_coord
{
    u8 Value;
    struct
    {
        u8 Ver: 4;     // 垂直（列）号
        u8 Hor: 4;     // 水平（行）号
    };
}key_coord_t;

typedef enum _key_status
{
    KEY_STATUS_RELEASE = 0,
    KEY_STATUS_PRESS
}key_status_t;

#ifdef _KEYBOARD_CONVERT_KEY_VALUE
typedef enum _key_value
{
    KEY_VALUE_ESC = 27,         KEY_VALUE_ESCAPE = 27,
    KEY_VALUE_ENTER = 13,       KEY_VALUE_RETURN = 13,
    KEY_VALUE_TAB = 9,
    KEY_VALUE_CAPS_LOCK = 20,   KEY_VALUE_CAPITAL = 20,
    KEY_VALUE_SHIFT = 10,
    KEY_VALUE_CTRL = 17,        KEY_VALUE_CONTROL = 17,
    KEY_VALUE_ALT = 18,         KEY_VALUE_MENU = 18,
    KEY_VALUE_SPACE = 32,
    KEY_VALUE_BACK = 8,
    KEY_VALUE_LWIN = 91,
    KEY_VALUE_RWIN = 92,
    KEY_VALUE_APPS = 93,
    KEY_VALUE_INSERT = 45,
    KEY_VALUE_HOME = 36,
    KEY_VALUE_PRIOR = 33,
    KEY_VALUE_NEXT = 34,
    KEY_VALUE_END = 35,
    KEY_VALUE_DELETE = 46,
    KEY_VALUE_LEFT = 37,
    KEY_VALUE_UP = 38,
    KEY_VALUE_RIGHT = 39,
    KEY_VALUE_DOWN = 40,
    KEY_VALUE_F1 = 112,
    KEY_VALUE_F2 = 113,
    KEY_VALUE_F3 = 114,
    KEY_VALUE_F4 = 115,
    KEY_VALUE_F5 = 116,
    KEY_VALUE_F6 = 117,
    KEY_VALUE_F7 = 118,
    KEY_VALUE_F8 = 119,
    KEY_VALUE_F9 = 120,
    KEY_VALUE_F10 = 121,
    KEY_VALUE_F11 = 122,
    KEY_VALUE_F12 = 123,
    KEY_VALUE_NUM_LOCK = 144,
    KEY_VALUE_NUMPAD0 = 96,
    KEY_VALUE_NUMPAD1 = 97,
    KEY_VALUE_NUMPAD2 = 98,
    KEY_VALUE_NUMPAD3 = 99,
    KEY_VALUE_NUMPAD4 = 100,
    KEY_VALUE_NUMPAD5 = 101,
    KEY_VALUE_NUMPAD6 = 102,
    KEY_VALUE_NUMPAD7 = 103,
    KEY_VALUE_NUMPAD8 = 104,
    KEY_VALUE_NUMPAD9 = 105,
    KEY_VALUE_DECIMAL = 110,
    KEY_VALUE_MULTIPLY = 106,
    KEY_VALUE_PLUS = 107,
    KEY_VALUE_SUBTRACT = 109,
    KEY_VALUE_DIVIDE = 111,
    KEY_VALUE_PAUSE = 19,
    KEY_VALUE_SCROLL = 145,
    KEY_VALUE_A = 65,
    KEY_VALUE_B = 66,
    KEY_VALUE_C,
    KEY_VALUE_D,
    KEY_VALUE_E,
    KEY_VALUE_F,
    KEY_VALUE_G,
    KEY_VALUE_H,
    KEY_VALUE_I,
    KEY_VALUE_J,
    KEY_VALUE_K,
    KEY_VALUE_L,
    KEY_VALUE_M,
    KEY_VALUE_N,
    KEY_VALUE_O,
    KEY_VALUE_P,
    KEY_VALUE_Q,
    KEY_VALUE_R,
    KEY_VALUE_S,
    KEY_VALUE_T,
    KEY_VALUE_U,
    KEY_VALUE_V,
    KEY_VALUE_W,
    KEY_VALUE_X,
    KEY_VALUE_Y,
    KEY_VALUE_Z,
    KEY_VALUE_0 = 48,
    KEY_VALUE_1,
    KEY_VALUE_2,
    KEY_VALUE_3,
    KEY_VALUE_4,
    KEY_VALUE_5,
    KEY_VALUE_6,
    KEY_VALUE_7,
    KEY_VALUE_8,
    KEY_VALUE_9,
}key_value_t;
#else   // 按照行列坐标表示键值
    typedef key_coord_t key_value_t;
#endif

/*
    按键状态缓存，排列如下：
   ___|            VER(列值)
   HOR 7   6   5   4   3   2   1   0
    0
    1
    2
    ...
*/
typedef struct _key_buff
{
    key_ver_t Data[_KEYBOARD_HOR];
}key_buff_t;



// keyboard 类，单例模式，不要实例化
typedef struct _keyboard
{   
    key_coord_t LastKey;    // 最后一次操作的按钮（坐标）
#ifdef _KEYBOARD_CONVERT_KEY_VALUE
    key_value_t LastKeyValue;
#endif
    key_status_t LastStatus;    // 最后一次状态[事件]
    key_buff_t KeyBuff;     // 所有按钮的状态[1:按下，0:松手]
    void (*EventCb)(const struct _keyboard * Sender);
}keyboard_t;


void Keyboard_Init();

// 设置回调函数，矩阵中任意按钮状态变化时会触发回调
void Keyboard_SetEventCb(void (*EventCb)(const keyboard_t * Sender));

// 获取最后一次操作的按键
key_value_t Keyboard_GetLastKey();

// 获取最后一次按键状态
key_status_t Keyboard_GetLastStatus();

// 获取按键缓存（所有按键状态[1:按下，0:松手]）
// 列用位表示，行用缓存角标表示。
key_buff_t * Keyboard_GetBuff();


#endif
